libxl: introduce lock in libxl_ctx
authorIan Jackson <ian.jackson@eu.citrix.com>
Mon, 12 Dec 2011 17:48:41 +0000 (17:48 +0000)
committerIan Jackson <ian.jackson@eu.citrix.com>
Mon, 12 Dec 2011 17:48:41 +0000 (17:48 +0000)
This lock will be used to protect data structures which will be hung
off the libxl_ctx in subsequent patches.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Committed-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl_internal.h

index e5cadb2c0a7ad1a008868e6952515712c685fd5d..7a973d0831173af81a9b1475755041427882bbc9 100644 (file)
@@ -41,6 +41,7 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
 {
     libxl_ctx *ctx;
     struct stat stat_buf;
+    const pthread_mutex_t mutex_value = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 
     if (version != LIBXL_VERSION)
         return ERROR_VERSION;
@@ -54,6 +55,11 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version,
     memset(ctx, 0, sizeof(libxl_ctx));
     ctx->lg = lg;
 
+    /* This somewhat convoluted approach is needed because
+     * PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP is defined to be valid
+     * only as an initialiser, not as an expression. */
+    memcpy(&ctx->lock, &mutex_value, sizeof(ctx->lock));
+
     if ( stat(XENSTORE_PID_FILE, &stat_buf) != 0 ) {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Is xenstore daemon running?\n"
                      "failed to stat %s", XENSTORE_PID_FILE);
index e66b86a08156bd886cf98b3be0ccaab154c10378..0fedcd9bd6e76888b70a254f4fed37f1dc599ff7 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <pthread.h>
 
 #include <xs.h>
 #include <xenctrl.h>
@@ -95,6 +96,18 @@ struct libxl__ctx {
     xc_interface *xch;
     struct xs_handle *xsh;
 
+    pthread_mutex_t lock; /* protects data structures hanging off the ctx */
+      /* Always use CTX_LOCK and CTX_UNLOCK to manipulate this.
+       *
+       * You may acquire this mutex recursively if it is convenient to
+       * do so.  You may not acquire this lock at the same time as any
+       * other lock.  If you need to call application code outside
+       * libxl (ie, a callback) with this lock held then it is
+       * necessaray to impose restrictions on the caller to maintain a
+       * proper lock hierarchy, and these restrictions must then be
+       * documented in the libxl public interface.
+       */
+
     /* for callers who reap children willy-nilly; caller must only
      * set this after libxl_init and before any other call - or
      * may leave them untouched */
@@ -669,6 +682,20 @@ libxl__device_model_version_running(libxl__gc *gc, uint32_t domid);
 #define CTX           libxl__gc_owner(gc)
 
 
+/* Locking functions.  See comment for "lock" member of libxl__ctx. */
+
+#define CTX_LOCK do {                                   \
+        int mutex_r = pthread_mutex_lock(&CTX->lock);   \
+        assert(!mutex_r);                               \
+    } while(0)
+
+#define CTX_UNLOCK do {                                 \
+        int mutex_r = pthread_mutex_unlock(&CTX->lock); \
+        assert(!mutex_r);                               \
+    } while(0)
+        
+
+
 /*
  * Inserts "elm_new" into the sorted list "head".
  *